home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Programming / LEDA / source / src / arith / igcd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-16  |  6.8 KB  |  391 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  3.1c
  4. +
  5. +
  6. +  igcd.c
  7. +
  8. +
  9. +  Copyright (c) 1994  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15. /*    igcd.c        RD, 21.03.90        */
  16.  
  17. /*    RD, 11.9.91, neues Ibgcd, Verdopplung der Geschwindigkeit. */
  18.  
  19. #include <LEDA/impl/iint.h>
  20. #include <LEDA/impl/iloc.h>
  21.  
  22. void Idgcd(d, a, b)
  23.     Integer *d;
  24.     const Integer *a, *b;
  25. /* d = gcd(a, b);   Euklidischer Algorithmus, Division mit Rest */
  26. {    Integer aa, bb, q, r;
  27.     register pInteger pa, pb, pq, pr, copy;
  28.     if (Ieq0(a)) {
  29.         IasI(d, b);
  30.         d->sign=PLUS;
  31.         return;
  32.     }
  33.     if (Ieq0(b)) {
  34.         IasI(d, a);
  35.         d->sign=PLUS;
  36.         return;
  37.     }
  38.     pa=&aa; pb=&bb; pq=&q; pr=&r;
  39.     cIasI(pa, a);
  40.     cIasI(pb, b);
  41.     cI(pq);
  42.     cI(pr);
  43.     pa->sign=PLUS;
  44.     pb->sign=PLUS;
  45.     while (TRUE) {
  46.         uIdiv(pq, pr, pa, pb);
  47.         if (Ieq0(pr))
  48.             break;
  49.         copy=pa; pa=pb; pb=pr; pr=copy;
  50.     }
  51.     IasI(d, pb);
  52.     dI(pa); dI(pb); dI(pq); dI(pr); 
  53. }        /* Idgcd */
  54.  
  55. #ifdef USE_OLD_BGCD
  56.  
  57. void Ibgcd(d, a, b)
  58.     pInteger d, a, b;
  59. /* d = gcd(a, b);   binaerer Algorithmus */
  60. {    register int toshift=0;
  61.     Integer aa, bb;
  62.     register pInteger pa, pb, swap;
  63.     if (Ieq0(a)) {
  64.         IasI(d, b);
  65.         d->sign=PLUS;
  66.         return;
  67.     }
  68.     if (Ieq0(b)) {
  69.         IasI(d, a);
  70.         d->sign=PLUS;
  71.         return;
  72.     }
  73.     pa=&aa; pb=&bb;
  74.     cIasI(pa, a);
  75.     cIasI(pb, b);
  76.     pa->sign=PLUS;
  77.     pb->sign=PLUS;
  78.     while (Ieven(pa) && Ieven(pb)) {
  79.         toshift++;
  80.         Isr1(pa);
  81.         Isr1(pb);
  82.     }
  83.     while (Ieven(pa)) {
  84.         Isr1(pa);
  85.     }
  86.     while (Ieven(pb)) {
  87.         Isr1(pb);
  88.     }
  89.     while (TRUE) {
  90.         if (IgtI(pb, pa)) {
  91.             swap=pa; pa=pb; pb=swap;
  92.         } else {
  93.             ImiasI(pa, pb);
  94.             if (!Ieq0(pa))
  95.                 while (Ieven(pa))
  96.                     Isr1(pa);
  97.             else
  98.                 break;
  99.     }    }
  100.     IasIslint(d, pb, toshift);
  101.     dI(pa);
  102.     dI(pb);
  103. }        /* Ibgcd */
  104.  
  105. #else
  106.  
  107. void Ibgcd(d, a, b)
  108.     Integer *d;
  109.     const Integer *a, *b;
  110. /*
  111.  * d = gcd(a, b);   binaerer Algorithmus, 
  112.  * direkt auf irv.c aufgesetzt.
  113.  * Achtung:
  114.  * Sind die Zahlen a, b sehr unterschiedlich gross, so ist
  115.  * Ibgcd relativ langsam. Deshalb ist es sinnvoll, vorher
  116.  * eine Division mit Rest durchzuf"uhren.
  117.  *
  118.  */
  119. {    register int l, al, bl;
  120.     int toshift=0;
  121.     Integer aa, bb;
  122.     register PLACE *lp, *avec, *bvec;
  123.     if (!a->length) {
  124.         IasI(d, b);
  125.         d->sign=PLUS;
  126.         return;
  127.     }
  128.     if (!b->length) {
  129.         IasI(d, a);
  130.         d->sign=PLUS;
  131.         return;
  132.     }
  133.     cI(&aa);
  134.     cI(&bb);
  135.     /* Nun zuerst eine Division mit Rest */
  136.     if (IgtI(a, b)) {
  137.         IasIreI(&aa, a, b);
  138.         if (!aa.length) {
  139.             IasI(d, b);
  140.             d->sign=PLUS;
  141.             dI(&aa);
  142.             dI(&bb);
  143.             return;
  144.         }
  145.         IasI(&bb, b);
  146.     } else {
  147.         IasIreI(&bb, b, a);
  148.         if (!bb.length) {
  149.             IasI(d, a);
  150.             d->sign=PLUS;
  151.             dI(&aa);
  152.             dI(&bb);
  153.             return;
  154.         }
  155.         IasI(&aa, a);
  156.     }
  157.     avec=aa.vec;
  158.     bvec=bb.vec;
  159.     al=aa.length;
  160.     bl=bb.length;
  161.     while (!(*avec & 1) && !(*bvec & 1)) {
  162.         toshift++;
  163.         vecsr1(avec, al);
  164.         if (!avec[al-1])
  165.             al--;
  166.         vecsr1(bvec, bl);
  167.         if (!bvec[bl-1])
  168.             bl--;
  169.     }
  170.     while (!(*avec & 1)) {
  171.         vecsr1(avec, al);
  172.         if (!avec[al-1])
  173.             al--;
  174.     }
  175.     while (!(*bvec & 1)) {
  176.         vecsr1(bvec, bl);
  177.         if (!bvec[bl-1])
  178.             bl--;
  179.     }
  180.     while (TRUE) {
  181.         if (bl>al || ((al==bl)&& vecgt(bvec, avec, bl))) {
  182.             lp=avec; avec=bvec; bvec=lp;
  183.             l=al; al=bl; bl=l;
  184.         } else {
  185.             lp=&(avec[al-1]);
  186.                     cvecsubto(avec, bvec, bl);
  187.             while ((al>0)&&(! *lp)) {
  188.                 al--; lp--;
  189.             }
  190.             if (al) 
  191.                 while (!(*avec & 1)) {
  192.                 register PLACE low;
  193.                 l=1;
  194.                 low=*avec>>1;
  195.                 while ( !(low & 1) && l<LOGRADIX-1 ) {
  196.                     l++;
  197.                     low>>=1;
  198.                 }
  199.                 vecsri(avec, al, l);
  200.                 if (!avec[al-1])
  201.                     al--;
  202.                 }
  203.             else
  204.                 break;
  205.     }    }
  206.     if (avec==aa.vec) {
  207.         bb.length=bl;
  208.         bb.sign=PLUS;
  209.         IasIslint(d, &bb, toshift);
  210.         dI(&aa);
  211.         dI(&bb);
  212.         return;
  213.     } else {
  214.         aa.length=bl;
  215.         aa.sign=PLUS;
  216.         IasIslint(d, &aa, toshift);
  217.         dI(&aa);
  218.         dI(&bb);
  219.         return;
  220.     }
  221. }        /* Ibgcd */
  222.  
  223. #endif
  224.  
  225. /*************************************************/
  226.  
  227. void Ielba(d, u, v, a, b)
  228.     Integer *d, *u, *v;
  229.     const Integer *a, *b;
  230. /* d = gcd(a, b) = ua + vb;   Euklid-Lenstra-Berlekamp */
  231. {    Integer aa, bb, wua, wva, wub, wvb, q, r;
  232.     register pInteger pa, pb, pq, pr, ua, va, ub, vb, copy;
  233.     if (Ieq0(a)) {
  234.         IasI(d, b);
  235.         Ias0(u);
  236.         Ias1(v);
  237.         v->sign=b->sign;
  238.         d->sign=PLUS;
  239.         return;
  240.     }
  241.     if (Ieq0(b)) {
  242.         IasI(d, a);
  243.         Ias1(u);
  244.         Ias0(v);
  245.         u->sign=a->sign;
  246.         d->sign=PLUS;
  247.         return;
  248.     }
  249.     pa=&aa; pb=&bb; pq=&q; pr=&r;
  250.     ua=&wua; va=&wva; ub=&wub; vb=&wvb;
  251.     cIasI(pa, a);
  252.     cIasI(pb, b);
  253.     cI(pq);
  254.     cI(pr);
  255.     pa->sign=PLUS;
  256.     pb->sign=PLUS;
  257.     cIasint(ua, 1);
  258.     ua->sign=a->sign;
  259.     cIasint(va, 0);        /* pa == ua*a + va*b */
  260.     cIasint(ub, 0);
  261.     cIasint(vb, 1);
  262.     vb->sign=b->sign;    /* pb == ub*a + vb*b */
  263.     while (TRUE) {
  264.         uIdiv(pq, pr, pa, pb);
  265.         if (Ieq0(pr))
  266.             break;
  267.         copy=pa; pa=pb; pb=pr; pr=copy;
  268.         IasImuI(pr, pq, ub);
  269.         copy=ua; ua=ub; ub=copy;
  270.         ImiasI(ub, pr);
  271.         IasImuI(pr, pq, vb);
  272.         copy=va; va=vb; vb=copy;
  273.         ImiasI(vb, pr);
  274.     }
  275.     IasI(d, pb);
  276.     IasI(u, ub);
  277.     IasI(v, vb);
  278.     dI(pa); dI(pb); dI(pq); dI(pr);
  279.     dI(ua); dI(ub); dI(va); dI(vb); 
  280. }        /* Ielba */
  281.  
  282. void Ibelba(d, u, v, a, b)
  283.     Integer *d, *u, *v;
  284.     const Integer *a, *b;
  285. /* d = gcd(a, b) = u*a + v*b;   binaerer Algorithmus */
  286. {    register int toshift=0;
  287.     Integer aa, bb, A, B, wxa, wxb, wya, wyb;
  288.     register pInteger pa, pb, pA, pB, xa, xb, ya, yb, swap;
  289.     if (Ieq0(a)) {
  290.         IasI(d, b);
  291.         Ias0(u);
  292.         Ias1(v);
  293.         v->sign=b->sign;
  294.         d->sign=PLUS;
  295.         return;
  296.     }
  297.     if (Ieq0(b)) {
  298.         IasI(d, a);
  299.         Ias1(u);
  300.         Ias0(v);
  301.         u->sign=a->sign;
  302.         d->sign=PLUS;
  303.         return;
  304.     }
  305.     pa=&aa; pb=&bb; xa=&wxa; xb=&wxb; ya=&wya; yb=&wyb;
  306.     pA=&A; pB=&B;
  307.     cIasI(pa, a);
  308.     cIasI(pb, b);
  309.     while (Ieven(pa) && Ieven(pb)) {
  310.         toshift++;
  311.         Isr1(pa);
  312.         Isr1(pb);
  313.     }
  314.     cIasI(pA, pa);
  315.     cIasI(pB, pb);
  316.     pa->sign=PLUS;
  317.     pb->sign=PLUS;
  318.     cIasint(xa, 1);
  319.     xa->sign=a->sign;
  320.     cIasint(ya, 0);        /* pa == xa*pA + ya*pB */
  321.     cIasint(xb, 0);
  322.     cIasint(yb, 1);
  323.     yb->sign=b->sign;    /* pb == xb*pA + yb*pB */
  324.     while (Ieven(pa)) {
  325.         Isr1(pa);
  326.         if (Ieven(xa) && Ieven(ya)) {
  327.             Isr1(xa);
  328.             Isr1(ya);
  329.         } else {
  330.             IplasI(xa, pB);
  331.             Isr1(xa);
  332.             ImiasI(ya, pA);
  333.             Isr1(ya);
  334.     }    }
  335.     while (Ieven(pb)) {
  336.         Isr1(pb);
  337.         if (Ieven(xb) && Ieven(yb)) {
  338.             Isr1(xb);
  339.             Isr1(yb);
  340.         } else {
  341.             IplasI(xb, pB);
  342.             Isr1(xb);
  343.             ImiasI(yb, pA);
  344.             Isr1(yb);
  345.     }    }
  346.     while (TRUE) {
  347.         if (IgtI(pb, pa)) {
  348.             swap=pa; pa=pb; pb=swap;
  349.             swap=xa; xa=xb; xb=swap;
  350.             swap=ya; ya=yb; yb=swap;
  351.         } else {
  352.             ImiasI(pa, pb);
  353.             ImiasI(xa, xb);
  354.             ImiasI(ya, yb);
  355.             if (!Ieq0(pa))
  356.                 while (Ieven(pa)) {
  357.                 Isr1(pa);
  358.                 if (Ieven(xa) && Ieven(ya)) {
  359.                     Isr1(xa);
  360.                     Isr1(ya);
  361.                 } else {
  362.                     IplasI(xa, pB);
  363.                     Isr1(xa);
  364.                     ImiasI(ya, pA);
  365.                     Isr1(ya);
  366.                 }    }
  367.             else
  368.                 break;
  369.     }    }
  370.     IasIslint(d, pb, toshift);
  371.     IasI(u, xb); IasI(v, yb);
  372.     dI(pa);    dI(pb);    dI(pA);    dI(pB);
  373.     dI(xa);    dI(xb);    dI(ya);    dI(yb);
  374. }        /* Ibelba */
  375.  
  376. /***********************************************/
  377.  
  378. void Ireduce(a, b)
  379.     pInteger a, b;
  380. /* Kuerze gcd von a und b */
  381. {    Integer d, r;
  382.     cI(&d);
  383.     cI(&r);
  384.     Ibgcd(&d, a, b);
  385.     Idiv(a, &r, a, &d);
  386.     Idiv(b, &r, b, &d);
  387.     dI(&d);
  388.     dI(&r);
  389. }
  390.